package com.llkj.common.http;

import android.support.annotation.NonNull;
import android.util.Log;

import com.llkj.common.http.interceptor.HeadersInterceptor;
import com.llkj.common.util.SSLUtil;

import java.util.concurrent.TimeUnit;

import io.reactivex.schedulers.Schedulers;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * author: zhu.px
 * e-mail: 1271901673@qq.com
 * time  : 2018/4/23
 * desc  :
 */
public class Api {

    /**
     * 全局配置
     */
    protected HttpGlobalConfig httpGlobalConfig;
    /**
     * 请求头
     */
    protected HttpHeaders headers = new HttpHeaders();
    private Retrofit retrofit;

    private Api() {
        generateGlobalConfig();
        generateLocalConfig();
    }

    /**
     * 生成全局配置
     */
    protected void generateGlobalConfig() {
        httpGlobalConfig = HttpUtils.getInstance();
        if (httpGlobalConfig.getBaseUrl() == null) {
            throw new IllegalStateException("Please call HttpUtils.getInstance().baseUrl() in Application to set baseUrl!");
        }
        HttpUtils.getRetrofitBuilder().baseUrl(httpGlobalConfig.getBaseUrl());

        if (httpGlobalConfig.getConverterFactorys().isEmpty()) {
            httpGlobalConfig.getConverterFactorys().add(GsonConverterFactory.create());
        }

        for (Converter.Factory factory : httpGlobalConfig.getConverterFactorys()) {
            HttpUtils.getRetrofitBuilder().addConverterFactory(factory);
        }

        if (httpGlobalConfig.getCallAdapterFactory() == null) {
            httpGlobalConfig.callAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()));
        }
        HttpUtils.getRetrofitBuilder().addCallAdapterFactory(httpGlobalConfig.getCallAdapterFactory());

        if (httpGlobalConfig.getCallFactory() != null) {
            HttpUtils.getRetrofitBuilder().callFactory(httpGlobalConfig.getCallFactory());
        }

        if (httpGlobalConfig.getHostnameVerifier() == null) {
            httpGlobalConfig.hostnameVerifier(new SSLUtil.UnSafeHostnameVerifier(httpGlobalConfig.getBaseUrl()));
        }
        HttpUtils.getOkHttpBuilder().hostnameVerifier(httpGlobalConfig.getHostnameVerifier());

        if (httpGlobalConfig.getSslSocketFactory() == null) {
            httpGlobalConfig.SSLSocketFactory(SSLUtil.getSslSocketFactory(null, null, null));
        }
        HttpUtils.getOkHttpBuilder().sslSocketFactory(httpGlobalConfig.getSslSocketFactory());

        if (httpGlobalConfig.getConnectionPool() == null) {
            httpGlobalConfig.connectionPool(new ConnectionPool(Config.DEFAULT_MAX_IDLE_CONNECTIONS,
                    Config.DEFAULT_KEEP_ALIVE_DURATION, TimeUnit.SECONDS));
        }
        HttpUtils.getOkHttpBuilder().connectionPool(httpGlobalConfig.getConnectionPool());
    }

    /**
     * 生成局部配置
     */
    private void generateLocalConfig() {
        OkHttpClient.Builder newBuilder = HttpUtils.getOkHttpClient().newBuilder();
        if (httpGlobalConfig.getGlobalHeaders() != null) {
            headers.put(httpGlobalConfig.getGlobalHeaders());
        }
        if (headers.headersMap.size() > 0) {
            newBuilder.addInterceptor(new HeadersInterceptor(headers.headersMap));
        }
        if (httpGlobalConfig.isLog()) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(@NonNull String message) {
                    Log.e(httpGlobalConfig.getLogTag(), message);
                }
            });
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            newBuilder.addInterceptor(loggingInterceptor);
        }
        HttpUtils.getRetrofitBuilder().client(newBuilder.build());
        retrofit = HttpUtils.getRetrofitBuilder().build();
    }

    public static Api getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public <T> T createApi(final Class<T> cls) {
        return retrofit.create(cls);
    }

    private static class SingletonHolder {
        private static Api INSTANCE = new Api();
    }
}
